﻿using System.Linq;
using System.Xml.Linq;
using NUnit.Framework;
using WB.Mvc.Forms.Widgets;

namespace WB.ComplianceStoreTests.Forms
{
	[TestFixture]
	public abstract class WidgetTestFixture
	{
		protected Widget widget;

		[SetUp]
		public void InitializeTest()
		{
			widget = CreateWidget();
		}

		[Test]
		public void ToHtml_Adds_Attribute()
		{
			widget.Attributes.Add("random", "value");
			string html = widget.ToHtml();

			XElement ele = XElement.Parse(html);

			Assert.IsNotNull(ele.Attribute("random"));
			Assert.AreEqual("value", ele.Attribute("random").Value);
		}

		[Test]
		public void Widget_Has_Id_Attribute()
		{
			string html = widget.ToHtml();

			XElement ele = XElement.Parse(html);

			XAttribute idAttribute = ele.Attribute("id");

			Assert.IsNotNull(idAttribute, "Should have found an id attribute.");
			Assert.AreEqual(widget.Name, idAttribute.Value);
		}

		[Test]
		public void Widget_Has_Name_Attribute()
		{
			string html = widget.ToHtml();

			XElement ele = XElement.Parse(html);

			XAttribute nameAttribute = ele.Attribute("name");

			Assert.IsNotNull(nameAttribute, "Expected to find a name attribute.");
			Assert.AreEqual(widget.Name, nameAttribute.Value);
		}

		[Test]
		public void Can_Set_Widget_Value()
		{
			const string widgetName = "widget";
			const string value = "something";

			widget.Value = value;
			string html = widget.ToHtml();

			XElement ele = XElement.Parse(html);

			XAttribute valueAttribute = ele.Attribute("value");

			Assert.IsNotNull(valueAttribute, "Expected to find a value attribute.");
			Assert.AreEqual(value, valueAttribute.Value);
		}

		protected abstract Widget CreateWidget();

		#region Nested type: CheckBoxFixture

		[TestFixture]
		public class CheckBoxFixture : WidgetTestFixture
		{
			[Test]
			public void Is_Input()
			{
				string html = widget.ToHtml();
				XElement ele = XElement.Parse(html);

				Assert.AreEqual("input", ele.Name.ToString());
			}

			[Test]
			public void Input_Is_Not_Checked()
			{
				string html = widget.ToHtml();
				XElement ele = XElement.Parse(html);

				XAttribute checkedAttrib = ele.Attribute("checked");

				Assert.IsNull(checkedAttrib, "CheckBox should not have checked attribute.");
			}

			[Test]
			public void Has_Value_Attribute()
			{
				Assert.IsTrue(widget.Attributes.ContainsKey("value"));
			}

			protected override Widget CreateWidget()
			{
				return new CheckBox("checkbox");
			}
		}

		#endregion

		#region Nested type: TextAreaFixture

		[TestFixture]
		public class TextAreaFixture : WidgetTestFixture
		{
			protected override Widget CreateWidget()
			{
				return new TextArea();
			}
		}

		#endregion

		#region Nested type: TextInputFixture

		[TestFixture]
		public class TextInputFixture : WidgetTestFixture
		{
			[Test]
			public void ToHtml_No_Max_Length()
			{
				var ti = new TextInput("name");
				string html = ti.ToHtml();
				XElement ele = XElement.Parse(html);

				Assert.AreEqual("input", ele.Name.ToString());
				Assert.AreEqual(string.Empty, ele.Attribute("value").Value);
			}

			[Test]
			public void ToHtml_Max_Length()
			{
				var ti = new TextInput("name", 1);
				string html = ti.ToHtml();
				XElement ele = XElement.Parse(html);

				Assert.IsNotNull(ele.Attribute("maxLength"), "Should have found a maxLength attribute.");
				Assert.AreEqual("1", ele.Attribute("maxLength").Value);
			}

			protected override Widget CreateWidget()
			{
				return new TextInput("name");
			}
		}

		#endregion

		[TestFixture]
		public class DropDownListFixture : WidgetTestFixture
		{
			protected DropDownList Widget
			{
				get { return widget as DropDownList; }
			}

			[Test]
			public void Options_Is_Not_Null()
			{
				Assert.IsNotNull(Widget.Options);
			}

			[Test]
			public void Can_Add_Options()
			{
				Widget.Options.Add(new ChoiceOption());
				Assert.AreEqual(1, Widget.Options.Count, "One option should have been in widget.");
			}

			[Test]
			public void ToHtml_Renders_Options()
			{
				Widget.Options.Add(new ChoiceOption("1", "1"));
				Widget.Options.Add(new ChoiceOption("2", "2"));

				var html = Widget.ToHtml();
				var ele = XElement.Parse(html);

				Assert.AreEqual(2, ele.Descendants("option").Count(), "Should have found two options elements.");
			}

			protected override Widget CreateWidget()
			{
				return new DropDownList();
			}
		}
	}
}